package alducente.media.sound {
	
	import alducente.media.sound.SoundDecorator;
	import flash.media.Sound;
	import flash.utils.Dictionary;
	import flash.utils.getDefinitionByName;
	import gs.TweenLite;
	
	public class SoundManager {
		//PRIVATE VARS
	
		//PROTECTED VARS
		protected var __soundDictionary:Dictionary;
	
		//PUBLIC VARS
	
		//CONSTRUCTOR
		public function SoundManager(){
			__soundDictionary = new Dictionary();
		}
	
		//PRIVATE FUNCTIONS
	
		//PROTECTED FUNCTIONS
		protected function addDecoratedSound(identifier:String, sound:SoundDecorator):void{
			if(soundExists(identifier)) throw new Error("A sound already exists with this identiier.");
			if(soundExists(sound)) throw new Error("This sound object already exists in the manager.");
			__soundDictionary[identifier] = sound;
		}
	
		//PUBLIC FUNCTIONS
		public function addSound(identifier:String, sound:*):void{
			if(sound is Sound){
				//create new decorator and add it
				var decorator:SoundDecorator = new SoundDecorator();
				decorator.sound = sound;
				addDecoratedSound(identifier, decorator);
			} else if(sound is SoundDecorator){
				//just add it
				addDecoratedSound(identifier, sound);
			} else {
				throw new Error("Can't add sound, it's not a valid datatype. Valid type are Sound and SoundDecorator.");
			}
		}
		
		public function removeSound(identifier:String):void{
			var sound:SoundDecorator;
			if(sound = getSoundDecorator(identifier)){
				if(sound.isPlaying) sound.stop();
				sound.sound = null;
				__soundDictionary[identifier] = null;
			} else {
				throw new Error("Can't remove sound, it doesn't exist in this manager.");
			}
		}
		
		public function soundExists(sound:*):Boolean{
			if(sound is String) return ((!__soundDictionary[sound])?false:true); 
			
			for (var key:String in __soundDictionary) {
			  	if(sound is Sound && (__soundDictionary[key].sound == sound)) return true;
				if(sound is SoundDecorator && (__soundDictionary[key] == sound)) return true;
			}
			return false;
		}
		
		public function getSoundDecorator(identifier:String):SoundDecorator{
			if(soundExists(identifier)){
				return __soundDictionary[identifier];
			}
			return null;
		}
		
		public function getIdentifier(sound:*):String{
			if(soundExists(sound)){
				for (var key:String in __soundDictionary) {
				  	if((sound is Sound && (__soundDictionary[key].sound == sound)) || (sound is SoundDecorator && (__soundDictionary[key] == sound))){
						return key;
					}
				}
			}
			return null;
		}
		
		public function play(identifier:String, volume:Number = 1, startTime:Number = 0, loops:int = 0):void{
			if(soundExists(identifier)){
				var decorator:SoundDecorator = getSoundDecorator(identifier);
				decorator.play(startTime, loops);
				decorator.vol = volume;
			}
		}
		
		public function stop(identifier:String):void{
			if(soundExists(identifier)) __soundDictionary[identifier].stop();
		}
		
		public function fadeTo(identifier:String, endVolume:Number, duration:Number, callback:Function=null):void{
			var s:SoundDecorator;
			if(s = getSoundDecorator(identifier)) TweenLite.to(s, duration, {vol: endVolume, onComplete: callback});
		}
		
		public function panTo(identifier:String, endPan:Number, duration:Number, callback:Function=null):void{
			var s:SoundDecorator;
			if(s = getSoundDecorator(identifier)) TweenLite.to(s, duration, {pan: endPan, onComplete: callback});
		}
		
		public function isPlaying(identifier:String):Boolean{
			if(getSoundDecorator(identifier)){
				return true;
			}
			return false;
		}
		
		//GETTERS & SETTERS
	}
}